package com.hb.trade.api.im.main;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.hb.trade.api.im.hall.handler.HallMessageHandler;
import lombok.extern.slf4j.Slf4j;
import org.fzzn.core.model.websocket.SocketMessageEntity;
import org.fzzn.core.websocket.config.WebSocketSession;
import org.springframework.stereotype.Component;

import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Objects;
import java.util.Set;

/**
 * 开标大厅的
 * websocket session
 */
@Slf4j
@Component
@ServerEndpoint("/websocket/{uname}")
public class TradeWebsocketSession extends WebSocketSession {

    protected Integer getInfoType(String message, Session session) {
        return super.onMessage(message, session);

    }

    @OnMessage
    @Override
    public Integer onMessage(String message, Session session) {
        Integer infoType = super.onMessage(message, session);
        if (infoType == null) {
            return null;
        }
        JSONObject msgJSON = JSONUtil.parseObj(message);
        // 根据消息类型判断处理逻辑
        switch (infoType) {
            case 1:
                //系统消息
                break;
            case 2:
                //即时通讯消息
                JSONObject dataContent = msgJSON.getJSONObject("dataContent");
                if (dataContent == null) {
                    log.warn("消息内容不能为空");
                    return null;
                }
                HallMessageHandler.handleIm(dataContent);
                break;
            //10 - 27 不能插入其他业务 只能是开标大厅
            case 10:
                //开标大厅签到开始
            case 11:
                //开标大厅开标开始
            case 12:
                //开标大厅解密开始
            case 13:
                //开标大厅解密结束
            case 14:
                //开标大厅唱标开始
            case 15:
                //开标大厅确认开始
            case 16:
                //开标大厅确认结束
            case 17:
                //开标大厅开标结束
            case 18:
                //开标大厅流标
            case 20:
                //投标人签到
            case 21:
                //投标人解密
            case 22:
                //投标人确认
            case 27:
                //播放会场纪律
                HallMessageHandler.handleHall(infoType, msgJSON);
                break;
            case 28:
                //发送系统消息  评标系统选举组长
                HallMessageHandler.sendSystem(infoType, msgJSON);
                break;
            case 29:
                //投标人再次报价
                HallMessageHandler.supplierQuoteAgain(infoType, msgJSON);
                break;
            case 30:
                //专家发起二轮报价
                HallMessageHandler.expertSendQuoteMsg(infoType, msgJSON);
                break;
            case 32:
                // 开标大厅暂停播放声音
                HallMessageHandler.stopPlay(msgJSON);
                break;
            default:
                break;
        }
        return null;
    }

    /**
     * 向客户端发送系统时间
     *
     * @param message
     * @throws IOException
     */
    public static void sendSystemTimeToAll(SocketMessageEntity message) throws IOException {
        for (WebSocketSession item : SYS_USER_SESSIONS) {
            if ("test".equals(item.getParamsValue("sectionId"))) {
                continue;
            }
            item.sendMessage(message);
        }
    }

    /***
     * 发送消息
     * @param message 消息
     */
    public static void send(SocketMessageEntity message) {
        // 获取接收人标识
        Set<String> toUnames = message.getUnames();
        // 没有接收人则全部发送，除了自己
        if (CollUtil.isEmpty(toUnames)) {
            sendExceptSelf(message);
            return;
        }
        sendTargetMsg(message, toUnames);
    }

    /***
     * 发送指定人消息
     * @param message 消息
     * @param toUnames 消息接收人
     */
    protected static void sendTargetMsg(SocketMessageEntity message, Set<String> toUnames) {
        log.debug("sendTargetMsg start with param toUnames is [{}]", toUnames);
        for (String toUname : toUnames) {
            // 没有接收人标识
            if (StrUtil.isEmpty(toUname)) {
                log.warn("toUname: {}, 接收人标识为空, 忽略本次发送", toUname);
                continue;
            }
            String fromName = message.getFromName();
            // 自己的消息不发送给自己
            if (toUname.equals(fromName)) {
                log.warn("toUname: {}, fromName: {}, 接收人与发送人相同, 忽略本次发送", toUname, fromName);
                continue;
            }
            JSONObject contentData = message.getContentData();
            log.info("推送系统消息到用户: {}, 推送内容: {}", toUname, contentData);
            try {
                String sectionId = null;
                if (CollUtil.isNotEmpty(contentData)) {
                    sectionId = contentData.getStr("sectionId");
                }
                WebSocketSession session = TradeWebsocketSession.get(toUname, sectionId);
                if (session == null) {
                    // 为null表示不在线
                    log.warn("toUname: {}, 用户不在线, 忽略本次发送", toUname);
                    // 消息进入离线数据库表哦
                    WebSocketSession.imChatService.record(message, toUname, true);
                } else {
                    // 判断是否拥有标段ID, 只发给同一标段的人的消息
                    String contentDataStr = contentData.getStr("sectionId");
                    if (StrUtil.equals(sectionId, contentDataStr)) {
                        session.sendMessage(message);
                    }
                }
            } catch (IOException e) {
                log.error("sendTargetMsg failed , errorMsg is [{}], stackInfo is ", e.getMessage(), e);
            }
        }
    }

    /***
     * 复写Equals方法
     * @param o
     * @return
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        if (!super.equals(o)) {
            return false;
        }
        TradeWebsocketSession that = (TradeWebsocketSession) o;
        String sectionId = getSectionId();
        String thatSectionId = that.getSectionId();
        return Objects.equals(uname, that.uname) && Objects.equals(sectionId, thatSectionId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(super.hashCode(), uname, getSectionId());
    }


    public String getSectionId() {
        if (CollUtil.isEmpty(params)) {
            return null;
        }
        String sectionId = params.getStr("sectionId");
        if (StrUtil.isEmpty(sectionId)) {
            return null;
        }
        return sectionId;
    }

}
